﻿using System;
using System.Collections.Generic;

namespace NodeJS.http
{
    using NodeJS.stream;
    /// <summary>
    /// This object is created internally by a HTTP server--not by the user. It is passed as the second parameter to the 'request' event.
    /// </summary>
    public abstract class ServerResponse : Writable
    {
        /// <summary>
        /// Indicates that the underlying connection was terminated before response.end() was called or able to flush.
        /// </summary>
        [EvalAtCompile(Value = "close")]
        public const NodeEvent CLOSE = null;

        /// <summary>
        /// Sends a HTTP/1.1 100 Continue message to the client, indicating that the request body should be sent.
        /// </summary>
        public abstract void WriteContinue();

        /// <summary>
        /// Sends a response header to the request. The status code is a 3-digit HTTP status code, like 404. The last argument, headers, are the response headers.
        /// </summary>
        /// <param name="statusCode"></param>
        /// <param name="props"></param>
        public abstract void WriteHead(int statusCode, Dictionary<string, string> props);

        /// <summary>
        /// This method signals to the server that all of the response headers and body have been sent; that server should consider this message complete. The method, response.end(), MUST be called on each response.
        /// If data is specified, it is equivalent to calling response.write(data, encoding) followed by response.end().
        /// </summary>
        /// <param name="content"></param>
        /// <param name="encoding"></param>
        public abstract void End(string content = "", string encoding = Encoding.Utf8);

        /// <summary>
        ///When using implicit headers (not calling response.writeHead() explicitly), this property controls the status code that will be sent to the client when the headers get flushed.
        /// </summary>
        public int StatusCode;

        /// <summary>
        /// Sets a single header value for implicit headers. If this header already exists in the to-be-sent headers, its value will be replaced.
        /// </summary>
        /// <param name="name"></param>
        /// <param name="val"></param>
        public abstract void SetHeader(string name, string val);

        /// <summary>
        /// Sets a single header value for implicit headers. If this header already exists in the to-be-sent headers, its value will be replaced.
        /// Use an array of strings here if you need to send multiple headers with the same name.
        /// </summary>
        /// <param name="name"></param>
        /// <param name="vals"></param>
        public abstract void SetHeader(string name, string[] vals);

        /// <summary>
        /// Reads out a header that's already been queued but not sent to the client. Note that the name is case insensitive. This can only be called before headers get implicitly flushed.
        /// </summary>
        /// <param name="name"></param>
        /// <returns></returns>
        public abstract string GetHeader(string name);

        /// <summary>
        /// Removes a header that's queued for implicit sending.
        /// </summary>
        /// <param name="name"></param>
        public abstract void RemoveHeader(string name);

        /// <summary>
        /// If this method is called and response.writeHead() has not been called, it will switch to implicit header mode and flush the implicit headers.
        /// This sends a chunk of the response body. This method may be called multiple times to provide successive parts of the body.
        /// </summary>
        /// <param name="chunk"></param>
        /// <param name="encoding"></param>
        /// <returns>Returns true if the entire data was flushed successfully to the kernel buffer. Returns false if all or part of the data was queued in user memory. 'drain' will be emitted when the buffer is again free.</returns>
        public abstract bool Write(StringOrBuffer chunk, string encoding = Encoding.Utf8);

        /// <summary>
        /// This method adds HTTP trailing headers (a header but at the end of the message) to the response.
        /// Trailers will only be emitted if chunked encoding is used for the response; if it is not (e.g., if the request was HTTP/1.0), they will be silently discarded.
        /// Note that HTTP requires the Trailer header to be sent if you intend to emit trailers, with a list of the header fields in its value.
        /// </summary>
        /// <param name="headers"></param>
        public abstract void AddTrailers(Dictionary<string, string> headers);

        /// <summary>
        /// Boolean (read-only). True if headers were sent, false otherwise.
        /// </summary>
        public readonly bool HeadersSent;

        /// <summary>
        /// When true, the Date header will be automatically generated and sent in the response if it is not already present in the headers. Defaults to true.
        /// This should only be disabled for testing; HTTP requires the Date header in responses.
        /// </summary>
        public bool SendDate;
    }
}
